var Amqp = require('../api/amqp').Amqp,
    Handler = require('../handlers/consumer').Consumer;
/**
 * Work with streaming content.
 *
 * The stream class provides methods that support multimedia streaming. The stream class uses the
 * following semantics: one message is one packet of data; delivery is unacknowleged and
 * unreliable; the consumer can specify quality of service parameters that the server can try to
 * adhere to; lower-priority messages may be discarded in favour of high priority messages.
 *
 * @class
 * @extends events.EventEmitter
 * @exports Stream as impl.Stream
 * @param handler
 */
function Stream(/**handlers.Channel*/channel, /**String*/consumerTag){
    var stream = this;
    this.handler = handler;
    /**
     * Confirm the requested qos.
     *
     * This method tells the client that the requested QoS levels could be handled by the server.
     * The requested QoS applies to all active consumers until a new QoS is defined.
     *
     * @name Stream#qos
     * @event
     */
    handler.addListener('Amqp.Stream.QosOk', function(){
        stream.emit('qos');
    });
    /**
     * Confirm a new consumer.
     *
     * This method provides the client with a consumer tag which it may use in methods that work
     * with the consumer.
     *
     * @name Stream#consume
     * @event
     * @param {String} consumerTag Identifier for the consumer, valid within the current
     *      connection.
     */
    handler.addListener('Amqp.Stream.ConsumeOk', function(frame){
        stream.emit('consume', frame.method.arguments.consumerTag);
    });
    /**
     * Confirm a cancelled consumer.
     *
     * This method confirms that the cancellation was completed.
     *
     * @name Stream#cancel
     * @event
     * @param {String} consumerTag Identifier for the consumer, valid within the current
     *      connection.
     */
    handler.addListener('Amqp.Stream.CancelOk', function(frame){
        stream.emit('cancel', frame.method.arguments.consumerTag);
    });
    /**
     * Return a failed message.
     *
     * This method returns an undeliverable message that was published with the "immediate" flag
     * set, or an unroutable message published with the "mandatory" flag set. The reply code and
     * text provide information about the reason that the message was undeliverable.
     *
     * @name Stream#return
     * @event
     * @param {Number} replyCode The reply code. The AMQ reply codes are defined in AMQ RFC 011.
     * @param {String} replyText The localised reply text. This text can be logged as an aid to
     *      resolving issues.
     * @param {String} exchange The exchange name is a client-selected string that identifies the
     *      exchange for publish methods. Exchange names may consist of any mixture of digits,
     *      letters, and underscores. Exchange names are scoped by the virtual host.
     * @param {String} routingKey Specifies the routing key name specified when the message was
     *      published.
     */
    handler.addListener('Amqp.Stream.Return', function(frame){
        var a = frame.method.arguments;
        stream.emit('return', a.replyCode, a.replyText, a.exchange, a.routingKey);
    });
    /**
     * Notify the client of a consumer message.
     *
     * This method delivers a message to the client, via a consumer. In the asynchronous message
     * delivery model, the client starts a consumer using the Consume method, then the server
     * responds with Deliver methods as and when messages arrive for that consumer.
     *
     * @name Stream#deliver
     * @event
     * @param {String} consumerTag Identifier for the consumer, valid within the current
     *      connection.
     * @param {Number} deliveryTag The server-assigned and channel-specific delivery tag.
     * @param {String} exchange The exchange name is a client-selected string that identifies the
     *      exchange for publish methods. Exchange names may consist of any mixture of digits,
     *      letters, and underscores. Exchange names are scoped by the virtual host.
     * @param {String} queue The queue name identifies the queue within the vhost. Queue names may
     *      consist of any mixture of digits, letters, and underscores.
     * @param {impl.Stream.Fields} fields
     * @param {String} body
     */
    handler.addListener('Amqp.Stream.Deliver', function(frame){
        var a = frame.method.arguments;
        stream.emit('deliver', a.consumerTag, a.deliveryTag, a.exchange, a.queue,
                frame.header.fields, frame.body);
    });
}
require('sys').inherits(Stream, require('events').EventEmitter);
/**
 * End a queue consumer.
 *
 * This method cancels a consumer. Since message delivery is asynchronous the client may continue
 * to receive messages for a short while after canceling a consumer. It may process or discard
 * these as appropriate.
 *
 * @param consumerTag Identifier for the consumer, valid within the current connection.
 * @param nowait If set, the server will not respond to the method. The client should not wait for
 *      a reply method. If the server could not complete the method it will raise a channel or
 *      connection exception.
 */
Stream.prototype.cancel = function(/**String*/consumerTag, /**Boolean*/nowait){
    this.handler.call(Amqp.Class.Stream, Amqp.Class.Stream.Cancel, { consumerTag: consumerTag,
        nowait: nowait });
};
/**
 * Start a queue consumer.
 *
 * This method asks the server to start a "consumer", which is a transient request for messages
 * from a specific queue. Consumers last as long as the channel they were created on, or until the
 * client cancels them.
 *
 * @param ticket An access ticket granted by the server for a certain set of access rights within a
 *      specific realm. Access tickets are valid within the channel where they were created, and
 *      expire when the channel closes.
 * @param queue The queue name identifies the queue within the vhost. Queue names may consist of
 *      any mixture of digits, letters, and underscores.
 * @param consumerTag Identifier for the consumer, valid within the current connection.
 * @param noLocal If <code>true</code> the server will not send messages to the client that
 *      published them.
 * @param exclusive Request exclusive consumer access, meaning only this consumer can access the
 *      queue.
 * @param nowait If set <code>true</code>, the server will not respond to the method. The client
 *      should not wait for a reply method. If the server could not complete the method it will
 *      raise a channel or connection exception.
 */
Stream.prototype.consume = function(/**Number*/ticket, /**String*/queue, /**String*/consumerTag,
        /**Boolean*/noLocal, /**Boolean*/exclusive, /**Boolean*/nowait){
    this.handler.call(Amqp.Class.Stream, Amqp.Class.Stream.Consume, { ticket: ticket, queue: queue,
        consumerTag: consumerTag, noLocal: noLocal, exclusive: exclusive, nowait: nowait });
};
/**
 * Publish a message.
 *
 * This method publishes a message to a specific exchange. The message will be routed to queues as
 * defined by the exchange configuration and distributed to any active consumers as appropriate.
 *
 * @param ticket An access ticket granted by the server for a certain set of access rights within a
 *      specific realm. Access tickets are valid within the channel where they were created, and
 *      expire when the channel closes.
 * @param exchange The exchange name is a client-selected string that identifies the exchange for
 *      publish methods. Exchange names may consist of any mixture of digits, letters, and
 *      underscores. Exchange names are scoped by the virtual host.
 * @param routingKey Specifies the routing key for the message. The routing key is used for routing
 *      messages depending on the exchange configuration.
 * @param mandatory This flag tells the server how to react if the message cannot be routed to a
 *      queue. If this flag is set, the server will return an unroutable message with a Return
 *      method. If this flag is zero, the server silently drops the message.
 * @param immediate This flag tells the server how to react if the message cannot be routed to a
 *      queue consumer immediately. If this flag is set, the server will return an undeliverable
 *      message with a Return method. If this flag is zero, the server will queue the message, but
 *      with no guarantee that it will ever be consumed.
 * @param fields
 * @param body
 */
Stream.prototype.publish = function(/**Number*/ticket, /**String*/exchange, /**String*/routingKey,
        /**Boolean*/mandatory, /**Boolean*/immediate, /**impl.Stream.Fields*/fields,
        /**String*/body){
    this.handler.call(Amqp.Class.Stream, Amqp.Class.Stream.Publish, { ticket: ticket,
        exchange: exchange, routingKey: routingKey, mandatory: mandatory, immediate: immediate },
        fields, body);
};
/**
 * Specify quality of service.
 *
 * This method requests a specific quality of service. The QoS can be specified for the current
 * channel or for all channels on the connection. The particular properties and semantics of a qos
 * method always depend on the content class semantics. Though the qos method could in principle
 * apply to both peers, it is currently meaningful only for the server.
 *
 * @param prefetchSize The client can request that messages be sent in advance so that when the
 *      client finishes processing a message, the following message is already held locally, rather
 *      than needing to be sent down the channel. Prefetching gives a performance improvement. This
 *      field specifies the prefetch window size in octets. May be set to zero, meaning "no
 *      specific limit". Note that other prefetch limits may still apply.
 * @param prefetchCount Specifies a prefetch window in terms of whole messages. This field may be
 *      used in combination with the prefetch-size field; a message will only be sent in advance if
 *      both prefetch windows (and those at the channel and connection level) allow it.
 * @param consumeRate Specifies a desired transfer rate in octets per second. This is usually
 *      determined by the application that uses the streaming data. A value of zero means "no
 *      limit", i.e. as rapidly as possible.
 * @param global By default the QoS settings apply to the current channel only. If this field is
 *      set, they are applied to the entire connection.
 */
Stream.prototype.qos = function(/**Number*/prefetchSize, /**Number*/prefetchCount,
        /**Number*/consumeRate, /**Boolean*/global){
    this.handler.call(Amqp.Class.Stream, Amqp.Class.Stream.Qos, { prefetchSize: prefetchSize,
        prefetchCount: prefetchCount, consumeRate: consumeRate, global: global });
};
exports.Stream = Stream;
/**
 * MIME content encoding.
 *
 * @name Stream.Fields
 * @class
 */
/**
 * MIME content type.
 *
 * @name Stream.Fields.contentEncoding
 * @type String
 */
/**
 * Message header field table.
 *
 * @name Stream.Fields.contentType
 * @type String
 */
/**
 * Message header field table.
 *
 * @name Stream.Fields.headers
 * @type Object
 */
/**
 * The message priority, 0 to 9.
 *
 * @name Stream.Fields.priority
 * @type Number
 */
/**
 * The message timestamp.
 *
 * @name Stream.Fields.timestamp
 * @type Date
 */
